package com.lie.prepare.multi_thread.mypractice.mypool;

import java.util.HashSet;
import java.util.Random;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.locks.ReentrantLock;

import static com.lie.prepare.util.Print.print;

/**
 * Created by lie on 2018/4/11.
 */
public class MyPool {

    private final BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>(10);

    //worker得抢到这个lock才能跑
    private final ReentrantLock mainLock = new ReentrantLock();

    private final HashSet<MyWorker> workers = new HashSet<MyWorker>();

    //模拟用
    private Random randomB = new Random(47);

    //一个worker代表一个工作线程，一个前台
    //它会不断的执行从任务队列中得到的任务
    private final class MyWorker implements Runnable{

        private Thread t;

        private Runnable firstTask;

        public MyWorker(Runnable task) {
            this.firstTask = task;
            //worker自己维护一个用来启动自己的线程
            t = new Thread(this);//源码是threadFactory
        }

        public void run() {
            runWorker(this);
        }

    }

    private boolean addWorker(Runnable task){
        //这里不考虑策略，无脑增加worker
        //策略1：假如队列是空的，则没必要增加worker
//        queue.isEmpty()
        MyWorker myWorker = new MyWorker(task);
        workers.add(myWorker);
        myWorker.t.start();//worker得在线程中跑

        return true;
    }

    //跑工作线程
    final void runWorker(MyWorker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;

        //提到外面来，那不同的worker之间也许有同步问题
        try {
            //只要worker第一个任务不为空，或者队列里的任务不为空，都要干活
            while (task != null || (task = getTask()) != null) {
                try {
                    task.run();

                }finally {
                    task = null;
                }
            }


        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        print(w + "没活干了");

    }

    public void execute(Runnable task){
        // TODO: 2018/4/11 模拟随机情况
        boolean isAddWorker = randomB.nextBoolean();
        if (isAddWorker) {
            print("核心线程数量足够 或者队列满但线程数没超最大数量,task = " +task);
            addWorker(task);
        }else {
            print("扔进队列里，让worker去慢慢去挨个执行,task = " +task);
            addTaskToQueue(task);
        }
    }


    public void addTaskToQueue(Runnable task){
        queue.offer(task);
    }

    public Runnable getTask() throws InterruptedException {
        try {
            Runnable task = queue.take();
            return task;
        } catch (InterruptedException e) {
//            e.printStackTrace();
            print("worker 取空队列在等待，但被打断");
            throw e;
        }
    }
}


